<template>
  <n-card :bordered="false">
    <data-table ref="menu_lists"
                :columns="menu_list_columns"
                :action-column="actionColumn"
                :row-key="(row:any) => row.id"
                list-url="menu/list"
                :pagination="false">
      <template #toolbarLeft>
        <n-button type="success" v-permission="['menu:add']" @click="()=>(addEditMenus=true)">
          <n-icon :size="18">
            <AddSharp/>
          </n-icon>
          新增
        </n-button>
      </template>
    </data-table>
  </n-card>
  <!--新增、编辑菜单数据-->
  <n-modal v-model:show="addEditMenus"
           :title="addEditMenusTitle"
           :show-icon="false"
           :mask-closable="false"
           preset="dialog"
           style="width: 690px"
           @after-leave="closeModel">
    <n-form ref="menuFormRef"
            :model="addEditMenusForm"
            :rules="addEditMenusFormRules"
            label-placement="left"
            label-width="80"
            require-mark-placement="left">
      <n-grid :cols="20" :x-gap="5">
        <n-form-item-gi :span="10" label="菜单类型" path="type">
          <n-radio-group v-model:value="addEditMenusForm.type" name="type" @update:value="changeTypes">
            <n-space>
              <n-radio :value="1">目录</n-radio>
              <n-radio :value="2">菜单</n-radio>
              <n-radio :value="3">按钮</n-radio>
            </n-space>
          </n-radio-group>
        </n-form-item-gi>
        <n-form-item-gi :span="10" label="是否外链" path="eLink" v-if="addEditMenusForm.type==2">
          <n-radio-group v-model:value="addEditMenusForm.eLink" name="eLink">
            <n-space>
              <n-radio :value="0">否</n-radio>
              <n-radio :value="1">是</n-radio>
            </n-space>
          </n-radio-group>
        </n-form-item-gi>
      </n-grid>
      <n-grid :cols="20" :x-gap="5">
        <n-form-item-gi :span="10" label="所属菜单" path="parentId">
          <n-tree-select v-model:value="addEditMenusForm.parentId" placeholder="请选择所属菜单"
                         :options="parentSelectOption" clearable/>
        </n-form-item-gi>
        <n-form-item-gi :span="10" label="菜单名称" path="label">
          <n-input v-model:value="addEditMenusForm.label" placeholder="请填写菜单名称" clearable/>
        </n-form-item-gi>
      </n-grid>
      <n-grid :cols="20" :x-gap="5">
        <n-form-item-gi :span="10" label="路由名称" path="name" v-if="addEditMenusForm.type!=3">
          <n-input v-model:value="addEditMenusForm.name" placeholder="请填写英文路由名称" clearable/>
        </n-form-item-gi>
        <n-form-item-gi :span="10" label="权限码" path="code" v-if="addEditMenusForm.type==1">
          <n-input v-model:value="addEditMenusForm.code" placeholder="如:sys:admin:add" clearable/>
        </n-form-item-gi>
        <n-form-item-gi :span="10" v-if="addEditMenusForm.type==2"
                        :label="addEditMenusForm.type==2 && addEditMenusForm.eLink==0?'组件路径':'外链地址'"
                        path="url">
          <n-input v-model:value="addEditMenusForm.url"
                   :placeholder="addEditMenusForm.type==2 && addEditMenusForm.eLink==0?'请填写组件路径':'请填写外链地址'"
                   clearable/>
        </n-form-item-gi>
      </n-grid>
      <n-grid :cols="20" :x-gap="5">
        <n-form-item-gi :span="10" label="权限码" path="code" v-if="addEditMenusForm.type!==1">
          <n-input v-model:value="addEditMenusForm.code" placeholder="如:sys:admin:add" clearable/>
        </n-form-item-gi>
        <n-form-item-gi :span="10" label="菜单序号" path="sort" v-if="addEditMenusForm.type==3">
          <n-input-number v-model:value="addEditMenusForm.sort" style="width: 100%" :min="1"
                          placeholder="请填写菜单序号"
                          :show-button="false" clearable/>
        </n-form-item-gi>
        <n-form-item-gi :span="10" label="菜单图标" path="icon" v-if="addEditMenusForm.type==1">
          <n-input v-model:value="addEditMenusForm.icon" placeholder="菜单图标" clearable/>
        </n-form-item-gi>
        <n-form-item-gi :span="10" label="菜单图标" path="icon" v-if="addEditMenusForm.type==2">
          <n-input v-model:value="addEditMenusForm.icon" placeholder="菜单图标" clearable/>
        </n-form-item-gi>
        <n-form-item-gi :span="10" label="菜单序号" path="sort" v-if="addEditMenusForm.type==1">
          <n-input-number v-model:value="addEditMenusForm.sort" style="width: 100%" :min="1"
                          placeholder="请填写菜单序号"
                          :show-button="false" clearable/>
        </n-form-item-gi>
      </n-grid>
      <n-grid :cols="20" :x-gap="5" v-if="addEditMenusForm.type!=3">
        <n-form-item-gi :span="10" label="菜单序号" path="sort" v-if="addEditMenusForm.type==2" :show-feedback="false">
          <n-input-number v-model:value="addEditMenusForm.sort" style="width: 100%" :min="1"
                          placeholder="请填写菜单序号"
                          :show-button="false" clearable/>
        </n-form-item-gi>
        <n-form-item-gi :span="10" label="是否显示" path="hideMenu" v-if="addEditMenusForm.type!==3" :show-feedback="false">
          <n-radio-group v-model:value="addEditMenusForm.hideMenu" name="hideMenu">
            <n-space>
              <n-radio :value="0">显示</n-radio>
              <n-radio :value="1">不显示</n-radio>
            </n-space>
          </n-radio-group>
        </n-form-item-gi>
      </n-grid>
    </n-form>
    <template #action>
      <n-space>
        <n-button @click="() => (addEditMenus = false)">取消</n-button>
        <n-button type="primary" :loading="handelSubmitLoading" @click="handelSubmitForm">
          确定
        </n-button>
      </n-space>
    </template>
  </n-modal>
</template>
<script setup lang="ts">
import {ref, onBeforeMount, h, reactive} from 'vue'
import {delRequest, getRequest, postPutRequest} from "@/api/data.ts";
import DataTable from '@components/DataTable'
import {NIcon, NPopconfirm, NTag, useMessage, FormInst, FormItemRule,TreeSelectOption} from "naive-ui";
import icons from "@/libs/icons.ts";
import {AddSharp} from "@vicons/material";
import DataTableAction from "@components/DataTable/src/components/DataTableAction/index.ts";

const message = useMessage()

//数据表ref
const menu_lists = ref<any>();
const menu_list_columns = ref([
  {
    title: '菜单名称',
    key: 'label',
  },
  {
    title: '类型',
    key: 'type',
    width: 70,
    render(row: { type: number }) {
      let type_color: string, type_text: string;
      switch (row.type) {
        case 1:
          type_text = '目录';
          type_color = 'info';
          break;
        case 2:
          type_text = '菜单';
          type_color = 'success';
          break;
        default:
          type_text = '按钮';
          type_color = 'warning';
      }
      return h(NTag,
          {
            type: <any>type_color,
            border: false
          },
          {
            default: () => (type_text),
          }
      );
    }
  },
  {
    title: '菜单图标',
    key: 'icon',
    width: 80,
    align: 'center',
    render(row: { icon: string }) {
      const icon = icons[row.icon];
      if (icon !== undefined) {
        return h(NIcon, {size: 18}, {
          default: () => h(icon)
        })
      }
    }
  }, {
    title: '路由名称',
    key: 'name',
    width: 130,
  }, {
    title: '权限码',
    key: 'code',
    width: 160,
  }, {
    title: '上级菜单',
    key: 'parentName'
  },{
    title:'排序',
    key:'sort',
    width:100,
    align: 'center',
  }, {
    title: '菜单栏中显示',
    key: 'hideMenu',
    align: 'center',
    width:110,
    render(row: { hideMenu: number }) {
      return h(NTag,
          {
            type: row.hideMenu ? 'error' : 'success',
          },
          {
            default: () => (row.hideMenu ? '不显示' : '显示'),
          }
      );
    }
  }, {
    title: '创建时间',
    key: 'create_time',
    width:175,
  },
])
const actionColumn = reactive({
  width: 120,
  title: "操作",
  key: "action",
  fixed: "right",
  render(record: Recordable) {
    let type_text: string;
    switch (record.type) {
      case 1:
        type_text = '目录';
        break;
      case 2:
        type_text = '菜单';
        break;
      default:
        type_text = '按钮';
    }
    return h(DataTableAction, {
      actions: [
        {
          label: '修改',
          onClick: handleEdit.bind(null, record),
          type: 'primary',
          permission: ['menu:edit']
        },
        {
          label: '删除',
          type: "error",
          popConfirm: NPopconfirm,
          onPositiveClick: handleDelete.bind(null, record),
          confirm: {
            text: '确定删除当前' + type_text + '吗？',
          },
          permission: ['menu:del']
        },
      ],
    });
  },
});

//新增、编辑菜单
const menuFormRef = ref<FormInst | null>(null)
const addEditMenus = ref(false);
const addEditMenusTitle = ref('新增目录');
const handelSubmitLoading = ref(false);
const parentSelectOption=ref<TreeSelectOption[]>([])
const addEditMenusForm = ref({
  id: 0,
  type: 1,
  eLink: 0,
  parentId: null,
  label: '',
  icon: '',
  name: '',
  url: '',
  code: '',
  sort: 100,
  hideMenu: 0
})
const addEditMenusFormRules = ref({
  type: {
    type: 'number',
    required: true,
    trigger: 'change',
    message: '请选择菜单类型'
  },
  eLink: {
    type: 'number',
    required: true,
    trigger: 'change',
    message: '请选择是否外链接'
  },
  parentId: {
    type: 'number',
    required: true,
    trigger: ['blur', 'change'],
    message: '请选择所属菜单'
  },
  label: {
    required: true,
    trigger: ['blur', 'input'],
    message: '请填写菜单名称'
  },
  name: {
    required: true,
    trigger: ['blur', 'input'],
    validator: (_rule: FormItemRule, value: string) => {
      return new Promise<void>((resolve, reject) => {
        let regex = /^[A-Za-z]+$/;
        if (!value) {
          reject(Error('请填写路由名称'))
        } else if (!regex.test(value)) {
          reject(Error('请填写英文路由名称')) // reject with error message
        } else {
          resolve()
        }
      })
    }
  },
  url: {
    required: true,
    trigger: ['blur', 'input'],
    message: '请填写组件路径'
  },
  code: {
    required: true,
    trigger: ['blur', 'input'],
    message: '请填写权限码'
  },
  sort: {
    type: 'number',
    trigger: ['blur', 'change'],
    validator: (_rule: FormItemRule, value: string) => {
      return new Promise<void>((resolve, reject) => {
        let regex = /^\d+$/;
        if (value && !regex.test(value)) {
          reject(Error('请填写正确的菜单序号'))
        } else {
          resolve()
        }
      })
    }
  },
})
//修改
const handleEdit = (record: Recordable) => {
  let title:string;
  switch (record.type) {
    case 1:
      title = '目录';
      break;
    case 2:
      title = '菜单';
      break;
    default:
      title = '按钮';
  }
  addEditMenusForm.value.id =record.id;
  addEditMenusForm.value.type = record.type;
  addEditMenusForm.value.eLink =record.elink;
  addEditMenusForm.value.parentId = record.parentId;
  addEditMenusForm.value.label = record.label;
  addEditMenusForm.value.icon = record.icon;
  addEditMenusForm.value.name = record.name;
  addEditMenusForm.value.url = record.url;
  addEditMenusForm.value.code =record.code;
  addEditMenusForm.value.sort = parseInt(record.sort);
  addEditMenusForm.value.hideMenu = record.hideMenu;
  addEditMenusTitle.value = '修改'+title;
  addEditMenus.value=true;
}
//删除
const handleDelete = (record: Recordable) => {
  delRequest('menu/del',record.id).then((result:ResponseResult)=>{
    if (result.status === 0 && result.code === 200) {
      message.success(result.message, {
        duration: 1500,
        onLeave() {
          menu_lists.value.reload();
        }
      })
    } else {
      message.error(result.message);
    }
  })
}
//关闭新增、修改菜单模态框
const closeModel = () => {
  addEditMenusForm.value.id = 0;
  addEditMenusForm.value.type = 1;
  addEditMenusForm.value.eLink = 0;
  addEditMenusForm.value.parentId = null;
  addEditMenusForm.value.label = '';
  addEditMenusForm.value.icon = '';
  addEditMenusForm.value.name = '';
  addEditMenusForm.value.url = '';
  addEditMenusForm.value.code = '';
  addEditMenusForm.value.sort = 100;
  addEditMenusForm.value.hideMenu = 0;
  addEditMenusTitle.value = '新增目录';
  handelSubmitLoading.value = false;
}
//提价新增、修改数据
const handelSubmitForm = (e: MouseEvent) => {
  e.preventDefault();
  menuFormRef.value?.validate((errors) => {
    if (!errors) {
     handelSubmitLoading.value = true;
      const url = addEditMenusForm.value.id ? 'menu/edit' : 'menu/add';
      postPutRequest(url, addEditMenusForm.value, addEditMenusForm.value.id ? 'PUT' : 'POST').then((result: ResponseResult) => {
        if (result.code === 200) {
          message.success(result.message, {
            duration: 1500,
            onLeave() {
              addEditMenus.value = false;
              menu_lists.value.reload();
              getMenuForSelect();
            }
          })
        } else {
          message.error(result.message);
          handelSubmitLoading.value = false;
        }
      })
    }
  })
}
//切换类型
const changeTypes = (value: string | number | boolean) => {
  const title_prefix = addEditMenusForm.value.id ? '修改' : '新增';
  let title: string;
  switch (value) {
    case 1:
      title = title_prefix + '目录';
      break;
    case 2:
      title = title_prefix + '菜单';
      break;
    default:
      title = title_prefix + '按钮';
  }
  addEditMenusForm.value.parentId = null;
  addEditMenusTitle.value = title;
}
//获取上级菜单
const getMenuForSelect = async () => {
  await getRequest("menu/parent_menus").then((result: ResponseResult) => {
    const {data} = result;
    const top_level: { label: string, key: number } = {label: '顶级菜单', key: 0};
    data.unshift(top_level);
    parentSelectOption.value=data;
  })
}
onBeforeMount(() => {
  getMenuForSelect();
})
</script>
<style scoped lang="scss">

</style>